package com.xcity.game.employee;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import com.xcity.db.entity.Employee;
import com.xcity.game.combat.attr.CombatAttribute;
import com.xcity.game.employee.template.EmployeeComboTemplate;
import com.xcity.game.employee.template.EmployeeExpTemplateV2;
import com.xcity.game.employee.template.EmployeeTemplate;
import com.xcity.game.formation.Formation;
import com.xcity.util.ExpCalculator;

import gnu.trove.list.TIntList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import naga.x.App;
import naga.x.game.template.TemplateService;

public class EmployeeUtils {

	private static Map<EmployeeQuality, ExpCalculator> /*expsV1, */expsV2; // v2: 20161230
	private static EmployeeTemplate defaultPlayerEmployeeTemplate; // 玩家对应的员工模板（用于生成玩家技能）
	private static TIntObjectMap<TIntList> comboRelatedIds = new TIntObjectHashMap<TIntList>(); // 羁绊关系
	
	public static final int DEFAULT_PLAYER_TEMPLATE_ID = 1;
	
	private static final Comparator<Employee> COMP = new Comparator<Employee>() {
		@Override
		public int compare(Employee e1, Employee e2) {
			// 1.阵型位置
			Formation f = e1.getVm().getOwner().getFormations().get(Formation.TYPE_NORMAL);
			int n1 = f.pos(e1);
			if (n1 != -1) n1 = Formation.FORMATION_CAPCITY - n1; // 在阵型中的位置越靠前，权重越大
			int n2 = f.pos(e2);
			if (n2 != -1) n2 = Formation.FORMATION_CAPCITY - n2;
			if (n1 < n2) {
				return 1;
			}
			if (n1 > n2) {
				return -1;
			}
			// 2.战斗力
			n1 = e1.getCombatPower();
			n2 = e2.getCombatPower();
			if (n1 < n2) {
				return 1;
			}
			if (n1 > n2) {
				return -1;
			}
			// 3.等级
			n1 = e1.getLevel();
			n2 = e2.getLevel();
			if (n1 < n2) {
				return 1;
			}
			if (n1 > n2) {
				return -1;
			}
			// 4.品级
			n1 = e1.getQualityLvl();
			n2 = e2.getQualityLvl();
			if (n1 < n2) {
				return 1;
			}
			if (n1 > n2) {
				return -1;
			}
			// 5.星级
			n1 = e1.getStarLvl();
			n2 = e2.getStarLvl();
			if (n1 < n2) {
				return 1;
			}
			if (n1 > n2) {
				return -1;
			}
			return e1.getId() > e2.getId() ? 1 : -1;
		}
	};
//	static {
////		initV1();
//		initV2();
//	}
	
//	@Deprecated
//	private static void initV1() {
//		List<EmployeeExpTemplate> expTemplates = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(EmployeeExpTemplate.class);
//		expsV1 = new EnumMap<>(EmployeeQuality.class);
//		int maxLevel = expTemplates != null ? expTemplates.size() : 0;
//		for (int i = 0; i < maxLevel; i++) {
//			EmployeeExpTemplate template = expTemplates.get(i);
//			int[] exps = template.getExp();
//			for (int j = 0; j < exps.length; j++) {
//				EmployeeQuality q = EmployeeQuality.of(j);
//				if (q == null) {
//					throw new RuntimeException("xlsx error: " + EmployeeExpTemplate.class + " -> level=" + template.getLevel() + ", col=" + j);
//				}
//				ExpCalculator val = expsV1.get(q);
//				if (val == null) {
//					val = new ExpCalculator(maxLevel);
//					expsV1.put(q, val);
//				}
//				val.setAndSum(template.getLevel(), exps[j]);
//			}
//		}
//	}
	
	public static void initV2() {
		List<EmployeeExpTemplateV2> expTemplates = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(EmployeeExpTemplateV2.class);
		expsV2 = new EnumMap<>(EmployeeQuality.class);
		int maxLevel = expTemplates.size();
		for (int i = 0; i < maxLevel; i++) {
			EmployeeExpTemplateV2 template = expTemplates.get(i);
			int[] exps = new int[] {
					template.getExpD(), template.getExpC(), template.getExpB(),
					template.getExpA(), template.getExpAA(), template.getExpAAA(),
					template.getExpS()
			};
			for (int j = 0; j < exps.length; j++) {
				EmployeeQuality q = EmployeeQuality.forCode(j);
				ExpCalculator val = expsV2.get(q);
				if (val == null) {
					val = new ExpCalculator(maxLevel);
					expsV2.put(q, val);
				}
				val.setAndSum(template.getLevel(), exps[j]);
			}
		}
	}
	
	private static ExpCalculator getCalculator(EmployeeQuality quality) {
		ExpCalculator calc = expsV2.get(quality);
//		return calc != null ? calc : expsV1.get(quality);
		return calc;
	}
	
	/**
	 * 由累计的经验计算等级
	 * @param exp 累计经验
	 * @param quality 员工品质
	 * @return
	 */
	public static int exp2Lvl(int exp, EmployeeQuality quality) {
		ExpCalculator calc = getCalculator(quality);
		return calc != null ? calc.exp2Lvl(exp) : 1;
	}
	
	/**
	 * 由累计的经验计算在当前等级范围内的经验
	 * @param exp
	 * @param quality
	 * @return
	 */
	public static int getCurrentExp(int exp, EmployeeQuality quality) {
		int level = exp2Lvl(exp, quality);
		ExpCalculator calc = getCalculator(quality);
		return calc.getCurrentLevelExp(level, exp);
	}
	
	/**
	 * 由当前等级计算下一等级所需经验（非累计）
	 * @param nowLvl
	 * @param quality
	 * @return
	 */
	public static int getNextLvlNeedExp(int nowLvl, EmployeeQuality quality) {
		ExpCalculator calc = getCalculator(quality);
		return calc != null ? calc.getExp(nowLvl + 1) : Integer.MAX_VALUE;
	}
	
	/**
	 * 达到某一等级所需的累计经验
	 * @param quality
	 * @return
	 */
	public static int getNeedTotalExp(EmployeeQuality quality, int level) {
		ExpCalculator calc = getCalculator(quality);
		return calc != null ? calc.getTotalExp(level) : Integer.MAX_VALUE;
	}
	
	public static int getMaxLevel(EmployeeQuality quality) {
		ExpCalculator calc = getCalculator(quality);
		return calc != null ? calc.getMaxLevel() : 40;
	}
	
	//---新版主属性v2---
//	/** 力量 */
//	@Deprecated
//	public static float getSTR(Employee employee) {
//		EmployeeTemplate template = employee.getTemplate();
//		return template.getSTR() + (employee.getLevel() - 1) * template.getSTR_DELTA();
//	}
//
//	/** 智力 */
//	@Deprecated
//	public static float getINT(Employee employee) {
//		EmployeeTemplate template = employee.getTemplate();
//		return template.getINT() + (employee.getLevel() - 1) * template.getINT_DELTA();
//	}
//	
//	/** 敏捷 */
//	@Deprecated
//	public static float getAGI(Employee employee) {
//		EmployeeTemplate template = employee.getTemplate();
//		return template.getAGI() + (employee.getLevel() - 1) * template.getAGI_DELTA();
//	}
//	
//	/** 精神 */
//	@Deprecated
//	public static float getSPI(Employee employee) {
//		EmployeeTemplate template = employee.getTemplate();
//		return template.getSPI() + (employee.getLevel() - 1) * template.getSPI_DELTA();
//	}
//	
//	/** 耐力 */
//	@Deprecated
//	public static float getSTA(Employee employee) {
//		EmployeeTemplate template = employee.getTemplate();
//		return template.getSTA() + (employee.getLevel() - 1) * template.getSTA_DELTA();
//	}
	//---新版主属性v2---
	
	public static List<CombatAttribute> initCombos(Employee employee) {
		List<EmployeeComboTemplate> templates = employee.getTemplate().getCombos();
		if (templates == null || templates.isEmpty()) {
			List<CombatAttribute> combos = Collections.emptyList();
			return combos;
		}
		EmployeeManager manager = employee.getVm();
		List<CombatAttribute> combos = null;
		for (int i = 0, size = templates.size(); i < size; i++) {
			EmployeeComboTemplate ect = templates.get(i);
			int[] viceIds = ect.getViceIds();
			boolean active = true;
			for (int viceId : viceIds) {
				int c = manager.size(viceId, null);
				if (c <= 0) {
					active = false;
					break;
				}
			}
			if (active) {
				CombatAttribute[] attrs = ect.getAttributes();
				for (CombatAttribute attr : attrs) {
					if (combos == null) {
						combos = new ArrayList<>();
					}
					combos.add(attr);
				}
			}
		}
		return combos != null ? combos : Collections.emptyList();
	}
	
	public static void addComboRelated(int id, int relatedId) {
		TIntList relatedIds = comboRelatedIds.get(id);
		if (relatedIds == null) {
			relatedIds = new TIntArrayList();
			comboRelatedIds.put(id, relatedIds);
		}
		relatedIds.add(relatedId);
	}
	
	public static TIntList getComboRelated(int id) {
		return comboRelatedIds.get(id);
	}
	
	public static EmployeeTemplate getPlayerTemplate() {
		if (defaultPlayerEmployeeTemplate == null) {
			defaultPlayerEmployeeTemplate = App.getApp().getServiceManager().get(TemplateService.class).get(EmployeeTemplate.class, DEFAULT_PLAYER_TEMPLATE_ID);
		}
		return defaultPlayerEmployeeTemplate;
	}
	
	public static void doSort(List<Employee> list) {
		Collections.sort(list, COMP);
	}
	
}
